﻿using System;
using System.Collections.Specialized;
using System.Collections.Generic;
using System.Linq;
using System.Data;
using System.Data.SqlClient;
using System.Reflection;
using System.IO;
using System.Text;
using Swd05.SH.Interfaces;
using NUnit.Framework;

namespace Swd05.SH
{
	[TestFixture(Description = "Testsuite für die SqlFactory")]
	public class SqlFactoryFixture
	{
		private string connectionstring = string.Empty;
		private string database			  = string.Empty;
		private IScriptFactory factory  = null;
		
		#region InnerClasses
		#region ScriptParser
		public class ScriptParser
		{
			private StringCollection coll = new StringCollection();
			private StringReader sr = null;
			public ScriptParser(string script)
			{
				this.sr = new StringReader(script);
			}
			#region Properties
			private StringCollection StringCollection
			{
				get 
				{ 
					return this.coll; 
				}
			}
			private StringReader Reader
			{
				get
				{
					return this.sr;
				}
			}
			internal StringCollection Scripts
			{
				get
				{
					return this.coll;
				}
			}
			#endregion
			#region Methods
			internal void Parse()
			{
				string line = "start";
				StringBuilder sb = null;
				try
				{
					/*
						anweisung
						GO
						anweisung
						GO
					*/

					sb = new StringBuilder();

					while ((line = this.Reader.ReadLine()) != null)
					{
						if (line.Trim() == "GO")
						{
							// ScriptEnde erreicht
							this.StringCollection.Add(sb.ToString());
							sb.Length = 0;
						}
						else
						{
							sb.Append(line);
							sb.Append(System.Environment.NewLine);
						}
					}
				}
				catch (Exception ex)
				{
					throw ex;
				}
				finally
				{
				}
			}
			#endregion
		}
		#endregion
		#endregion


		#region Properties
		private string Server
		{
			get
			{
				return System.Configuration.ConfigurationSettings.AppSettings["Server"].ToString();
			}
		}
		private string Database
		{
			get
			{
				return this.database;
			}
		}
		public string Connectionstring
		{
			get
			{
				return this.connectionstring;
			}
		}
		private IScriptFactory Factory
		{
			get
			{
				return this.factory;
			}
		}
		#endregion
		#region methods
		[TestFixtureSetUp]
		public void TestFixtureSetUp()
		{
			this.database = string.Format("{0}_Scripts", System.Environment.UserName);
			this.connectionstring = String.Format( @"server={0};trusted_connection=yes", this.Server );
			
			this.RunDbScripts();
			
			this.factory = Facade.Instance.Create( Bll.Source.Sql, string.Format( "{0};database={1}", this.Connectionstring, this.Database ) );
			
		}
		[TestFixtureTearDown]
		public void TestFixtureTearDown()
		{
			this.RunDbScript( this.LoadScriptById( "Swd05.SH.Test.Resources.Sql.sql.db.drop.sql" ));
		}
		[SetUp]
		public void TestSetup()
		{
		}
		[TearDown]
		public void TestTearDown()
		{
		}
		[Test]
		public void FindNonExistingScriptById()
		{
			FactoryTester ft = new FactoryTester( this.Factory );
			ft.FindNonExistingScript();
		}
		[Test]
		public void FindExistingScriptById()
		{
			FactoryTester ft = new FactoryTester(this.Factory);
			ft.FindExistingScriptById();
		}
		[Test]
		public void RetrieveScriptContent()
		{
			FactoryTester ft = new FactoryTester(this.Factory);
			ft.RetrieveScriptContent();
		}
		[Test]
		public void UpdateScriptContent()
		{
			FactoryTester ft = new FactoryTester(this.Factory);
			ft.RetrieveScriptContent();
		}
		[Test]
		public void RemoveScriptContent()
		{
			FactoryTester ft = new FactoryTester(this.Factory);
			ft.RemoveScriptContent();
		}
		[Test]
		public void LoadAllScripts()
		{
			FactoryTester ft = new FactoryTester(this.Factory);
			ft.Load();
		}
		private void RunDbScripts()
		{
			string script = string.Empty;
			int counter = 0;

			while ( true )
			{
				script = this.LoadScriptById(string.Format("Swd05.SH.Test.Resources.Sql.sql.script.{0}.sql", counter.ToString()));
				counter ++;
				if (script.Length == 0)
				{
					break;
				}
				this.RunDbScript(script);
			}
			return;
		}
		private string LoadScriptById( string id )
		{
			String script = String.Empty;
			using (Stream stream = Assembly.GetExecutingAssembly().GetManifestResourceStream( id ) )
			{
				if (stream != null)
				{
					using (StreamReader sr = new StreamReader(stream, System.Text.Encoding.Default))
					{
						script = sr.ReadToEnd();
					}
				}
			}
			return script;
		}
		private void RunDbScript(string script)
		{
			System.Data.SqlClient.SqlCommand cmd = null;
			ScriptParser p = null;

			p = new ScriptParser(script);
			p.Parse();

			using ( SqlConnection conn = new System.Data.SqlClient.SqlConnection( this.Connectionstring ))
			{
				conn.Open();
				foreach (string s in p.Scripts)
				{
					
					cmd = new System.Data.SqlClient.SqlCommand(s.Replace( "{database}", this.Database ), conn);
					cmd.ExecuteNonQuery();
				}
			}
		}
		#endregion
	}
}
